package com.lagou.rpc.consumer.zookeeper;

import com.lagou.rpc.consumer.client.RpcClient;
import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.ZkClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * zookeeper客户端操作类
 */
@Component
public class ZookeeperClientOperation implements IZkChildListener {

    private static final Logger LOGGER = (Logger) LoggerFactory.getLogger(ZookeeperClientOperation.class);

    private String zookeeperAddress = "127.0.0.1:2181";

    private static final String ROOT_NODE = "/lg-provider";

    private static final List<String> RPC_CLIENTS = new ArrayList<>();

    @PostConstruct
    public void init(){
        // 初次获取服务提供者
        ZkClient zkClient = new ZkClient(zookeeperAddress);
        List<String> serviceList = zkClient.getChildren(ROOT_NODE);
        handleChildChange(ROOT_NODE, serviceList);
        // 注册监听
        zkClient.subscribeChildChanges(ROOT_NODE, new ZookeeperClientOperation());
    }

    /**
     * watch子节点发生变更
     * @param path
     * @param list
     */
    @Override
    public void handleChildChange(String path, List<String> list) {
        LOGGER.info("服务提供者列表:{},{}", path, list);
        RPC_CLIENTS.clear();
        RPC_CLIENTS.addAll(list);
    }

    /**
     * 获取RpcClient
     * @return
     */
    public RpcClient getRpcClient() {
        if (CollectionUtils.isEmpty(RPC_CLIENTS)){
            return null;
        }
        // 遍历RpcClient，选择响应时间短的服务端进行调用
        ZkClient zkClient = new ZkClient(zookeeperAddress);
        RpcClient selectedClient = null;
        long lastResponseTime = 0;
        for (String clientInfo : RPC_CLIENTS) {
            // 创建RpcClient
            String[] ipAndPort = clientInfo.split(":");
            RpcClient rpcClient;
            try {
                rpcClient = new RpcClient(ipAndPort[0], Integer.parseInt(ipAndPort[1]));
            } catch (NumberFormatException e) {
                continue;
            }
            // 获取响应时间
            String nodeName = ROOT_NODE + "/" + rpcClient.getAddress();
            Object data = zkClient.readData(nodeName);
            LOGGER.info("服务提供者:{}, 最近响应时间:{}", rpcClient.getAddress(), data.toString());
            long time = 0;
            if (data != null && !"".equals(data)){
                time = Long.parseLong(data.toString());
            }
            if (selectedClient == null){
                selectedClient = rpcClient;
                lastResponseTime = time;
                continue;
            }
            // 选择响应时间最短的服务端
            if (time < lastResponseTime){
                selectedClient = rpcClient;
                lastResponseTime = time;
            }
        }
        return selectedClient;
    }

}
